package com.yllt4cloud.push.server;

import com.alibaba.fastjson.JSONObject;
import com.yllt4cloud.common.ddbase.constant.ErrorCode;
import com.yllt4cloud.common.ddbase.constant.NettyConstants;
import com.yllt4cloud.common.ddbase.constant.entity.CryptEnum;
import com.yllt4cloud.common.ddbase.constant.entity.SessionEntity;
import com.yllt4cloud.common.ddbase.message.Message;
import com.yllt4cloud.common.ddbase.message.RequestMessage;
import com.yllt4cloud.common.ddbase.util.Base64Utils;
import com.yllt4cloud.common.ddbase.util.CommonRedisUtil;
import com.yllt4cloud.common.ddbase.util.JsonUtil;
import com.yllt4cloud.common.ddbase.util.crypto.CryptoManager;
import com.yllt4cloud.push.util.SocketUtil;
import org.apache.commons.lang3.StringUtils;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.*;
import org.jboss.netty.handler.codec.http.*;
import org.jboss.netty.handler.codec.http.websocketx.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

/**
 * 作者:chenpeng E-mail:46731706@qq.com 创建时间：2012-7-12 下午12:02:52 游戏协议接收分发器
 */
@Component
public class ServerHandler extends SimpleChannelUpstreamHandler {

	private static final Logger logger = LoggerFactory
			.getLogger(ServerHandler.class);

//	@Autowired
//	private RedisTemplate redisTemplate;

	@Autowired
	private HandlerDispatcher handlerDispatcher;

	@Autowired
	private SocketUtil socketUtil;

	@Autowired
	CommonRedisUtil commonRedisUtil;
/*
	@Autowired
	private IRoomService roomService;
	@Autowired
	private IZhangDanService zhangDanService;
	@Autowired
	private SocketUtil socketUtil;
	@Autowired
    private IIpadLuoDanJiLuService ipadLuoDanJiLuService;
*/

	private boolean debug = false;

	// 初始化的时候装载了
	@PostConstruct
	public void init() {
		// 分发器开始工作
		new Thread(handlerDispatcher).start();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelConnected
	 * (org.jboss.netty.channel.ChannelHandlerContext,
	 * org.jboss.netty.channel.ChannelStateEvent) 建立一个新channel
	 */
	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		NettyServer.allChannels.add(e.getChannel());
		//logger.debug("进来一个channel：" + ctx.getChannel().getId());
		// handlerDispatcher.sendMessage(e.getChannel(), Message.success("1"));
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelDisconnected
	 * (org.jboss.netty.channel.ChannelHandlerContext,
	 * org.jboss.netty.channel.ChannelStateEvent) 玩家主动关闭channel
	 */
	@Override
	public void channelDisconnected(ChannelHandlerContext ctx,
			ChannelStateEvent e) throws Exception {
		handlerDispatcher.removeUser(e.getChannel());
		//logger.error("关掉一个channel：" + ctx.getChannel().getId());
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.jboss.netty.channel.SimpleChannelUpstreamHandler#exceptionCaught(
	 * org.jboss.netty.channel.ChannelHandlerContext,
	 * org.jboss.netty.channel.ExceptionEvent) 玩家被动关闭channel
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
        logger.error("出异常啦……" + ctx.getChannel().getId());
        handlerDispatcher.removeUser(e.getChannel());
    }

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.jboss.netty.channel.SimpleChannelUpstreamHandler#messageReceived(
	 * org.jboss.netty.channel.ChannelHandlerContext,
	 * org.jboss.netty.channel.MessageEvent) 消息接收处理器
	 */
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		Channel ch = e.getChannel();
		Object object = e.getMessage();
		// System.out.println(object.getClass().getName());

		if (object instanceof HttpRequest) {
			processHttpRequest(ch, (HttpRequest) object);
		} else if (object instanceof WebSocketFrame) {
			processWebsocketRequest(ch, (WebSocketFrame) object);
		} else {
			// 未处理的请求类型
			logger.error("非法请求类型");
		}

	}

	void processHttpRequest(Channel channel, HttpRequest request) {
		HttpHeaders headers = request.headers();
		if (debug) {
			List<Map.Entry<String, String>> ls = headers.entries();
			for (Map.Entry<String, String> i : ls) {
				//logger.info("header  " + i.getKey() + ":" + i.getValue());
			}
		}
		ChannelBuffer channelBufferl = request.getContent();
		byte[] bytel = channelBufferl.array();
		String text = new String(bytel);

		// non-get request
		// 屏蔽掉非websocket握手请求
		// 只接受http GET和headers['Upgrade']为'websocket'的http请求
		if (!HttpMethod.GET.equals(request.getMethod())
				|| !"websocket".equalsIgnoreCase(headers.get("Upgrade"))) {
			DefaultHttpResponse resp = new DefaultHttpResponse(
					HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
			channel.write(resp);
			channel.close();
			return;
		}

		WebSocketServerHandshakerFactory wsShakerFactory = new WebSocketServerHandshakerFactory(
				"ws://" + request.headers().get(HttpHeaders.Names.HOST), null,
				false);
		WebSocketServerHandshaker wsShakerHandler = wsShakerFactory
				.newHandshaker(request);
		if (null == wsShakerHandler) {
			// 无法处理的websocket版本
			wsShakerFactory.sendUnsupportedWebSocketVersionResponse(channel);
		} else {
			// 向客户端发送websocket握手,完成握手
			// 客户端收到的状态是101 sitching protocol
			wsShakerHandler.handshake(channel, request);
		}
	}

	void processWebsocketRequest(Channel channel, WebSocketFrame request)
			throws Exception {
		if (request instanceof CloseWebSocketFrame) {
			// handlerDispatcher.removeMessageQueue(channel.getId());
			channel.close().sync();
		} else if (request instanceof PingWebSocketFrame) {

			ChannelBuffer channelBuffer = request.getBinaryData();
			String s = new String(channelBuffer.array());
			channel.write(new PongWebSocketFrame(request.getBinaryData()));
		} else if (request instanceof TextWebSocketFrame) {
			// 这个地方 可以根据需求，加上一些业务逻辑
			TextWebSocketFrame txtReq = (TextWebSocketFrame) request;
			// if (debug) {

			// ChannelBuffer channelBuffer=request.getContent();
			// byte[] bytes = channelBuffer.array();
			String s = txtReq.getText();

			logger.info("连接一个channel:"+s);
			if (StringUtils.isNotBlank(s)) {
				RequestMessage message = JsonUtil.parseObject(s,
						RequestMessage.class);

				//过滤紧急列印
				if (message.getType() != null
						&& !StringUtils.isEmpty(message.getType()) && message.getType().equals(NettyConstants.EMERGENCY_PRINT_GROUP_NAME)) {

//					String userId = message.getType() + (int)(Math.random()*100);
					String userId = message.getType();
                    Integer sheBeiId = message.getSheBeiId();
                    if(sheBeiId==null){
                        sheBeiId = -1;
                    }
					//设置紧急列印推送
					handlerDispatcher.addUser(userId, channel,String.valueOf(sheBeiId));
					handlerDispatcher.addGroupMember(message.getType(),
							userId);
					return;
				}
				String session = message.getSession();

				// 判断session是否为空
				if (StringUtils.isEmpty(session)) {
					logger.error("用户未登陆。关闭回话");
					// handlerDispatcher.removeUser(channel);
					sendUnLoginMessage(channel);
					return;
				}
				String contents = Base64Utils
						.decodeToString(session.toString());
				Map<String, Object> sessionMap = JsonUtil.parseMap(contents);
				String token = (String) sessionMap.get("token");
				String sessionId = (String) sessionMap.get("user");

				logger.info("token-{},sessionId-{}", token, sessionId);
//				redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
				SessionEntity sessionEntity = (SessionEntity) commonRedisUtil.getSessionEntity(session);
//						redisTemplate.opsForValue().get(CacheConstants.DD_SESSION_CONTAINER+":"+session);

//				SessionEntity sessionEntity = UserSessionContainer.instance()
//						.get(sessionId);

				// 有登录要求的才有用户信息
				if (null == sessionEntity) {
					logger.error("用户未登陆。关闭回话");
					// handlerDispatcher.removeUser(channel);
					sendUnLoginMessage(channel);
					return;
				}
				// UserSessionContainer.instance().put(sessionId,
				// sessionEntity);

				String key = sessionEntity.getEncryptKey();
				// 签名校验(session中的token和本地token必须一致)
				if (!token.equals(sessionEntity.getToken())) {
					logger.error("用户未登陆。关闭回话");
					// handlerDispatcher.removeUser(channel);
					sendUnLoginMessage(channel);
					return;
				}
               //取当前登入的，clerkId,现在点单登入的时候是没有 userId
                String userId = sessionEntity.getUserInfo().getClerkId() + "";
				logger.info("连接推送的用户id:"+userId);

                Integer ipadUserId = Integer.parseInt(userId);

				//String userId = sessionEntity.getUserInfo().getUserId() + "";
				if (message.getType() != null && !StringUtils.isEmpty(message.getType())) {

                    String data = message.getData();
                    String sheBeiId = "-1";
                    if (data != null && !StringUtils.isEmpty(data)) {
                        Integer encryptType =  message.getEncryptType();//加密类型 0不加密 1加密
                        if(encryptType!=null && encryptType.equals(1)){
                            // 解密
                            data = CryptoManager.getInstance()
                                .getCrypto(CryptEnum.AES)
                                .decrypt(data, key);
                        }
                        JSONObject json = JSONObject.parseObject(data);
                        sheBeiId = json.getString("sheBeiId");
                        logger.info("连接推送的设备id:"+sheBeiId);
                    }

                    if (message.getType().equals(NettyConstants.ROOM_HOME_SHOUYIN)||message.getType().equals(NettyConstants.JFK_GROUP_NAME)) {//收银主界面和即付款
                        userId = message.getType() + "_" + sheBeiId+ "_" + userId;
                    }else{
                        userId = message.getType() + "_" + userId;
                    }

					handlerDispatcher.addUser(userId, channel,String.valueOf(sheBeiId));

					if (message.getType().equals(
							NettyConstants.CHUPIN_DIAN_GROUP_NAME)) {
						// 将数据进行转换
						if (data != null && !StringUtils.isEmpty(data)) {
							// 解密
							data = CryptoManager.getInstance()
									.getCrypto(CryptEnum.AES)
									.decrypt(data, key);

							JSONObject json = JSONObject.parseObject(data);

							handlerDispatcher.addGroupMember(message.getType()
									+ "_" + json.getString("sheBeiId"), userId);
						}
					//收银统计。第一次链接发送数据
					}else if (message.getType().equals(
							NettyConstants.SHOU_YIN_COUNT_GROUP_NAME)){
						handlerDispatcher.addGroupMember(message.getType(),
								userId);
						//获取收银统计数据
//						Map<String, Object> paramMap = new HashMap<String, Object>();
//                        paramMap.put("riQi", SystemConfigContainer.instance().getWorkDate());
//                        paramMap.put("isInvalid", GlobalConstants.FALSE);
//                        BannerConsumeCount bannerConsumeCount = zhangDanService.getBannerConsumeCount(paramMap);
//
//						//推送收银统计数据
//						handlerDispatcher.sendGroupMessage(NettyConstants.SHOU_YIN_COUNT_GROUP_NAME, Message.success(bannerConsumeCount));
					}else if (message.getType().equals(
							NettyConstants.SHAN_MI_KAO_QIN_COUNT_GROUP_NAME)){
						handlerDispatcher.addGroupMember(message.getType(),
								userId);
						socketUtil.sendShanMiKaoQinRenShu();
					}else if(message.getType().equals(
                        NettyConstants.ROOM_KAIFANG_COUNT)){
                        handlerDispatcher.addGroupMember(message.getType(),
                            userId);
                        //推送咨客开房统计
//                        socketUtil.sendRoomKaiFangCount(message.getType());
                    }else if (message.getType().equals(
                        NettyConstants.IPAD_SHOU_YIN_GROUP_NAME)){
                        handlerDispatcher.addGroupMember(message.getType(),
                            userId);
                        //获取收银统计数据
//                        IpadBannerConsumeCount roomConsumeCount = ipadLuoDanJiLuService.countIpadBannerValue(ipadUserId);
//                        handlerDispatcher.sendMessage(NettyConstants.IPAD_SHOU_YIN_GROUP_NAME+"_"+ipadUserId+"", Message.success(roomConsumeCount));
//                        logger.info("ipad用户"+ipadUserId+"连接已发送banner推送");
                    }else {
						handlerDispatcher.addGroupMember(message.getType(),
								userId);
					}

				}
			}

			// }
			if ("disconnect".equalsIgnoreCase(txtReq.getText())) {

				handlerDispatcher.removeUser(channel);
				return;
			}
			// 把符合条件的channel添加到DynMessage的channelGroup中
			// DynMessage.addAudience(channel);
		} else {
			// WebSocketFrame还有一些
		}
	}



	/**
	 *
	 * <p>
	 * <b>作用：</b>对指定通道发送未登陆信息
	 * </p>
	 * <p>
	 * <b>日期：</b>2016-4-5 下午2:49:13
	 * </p>
	 * <p>
	 * <b>作者：</b>yaozq
	 * </p>
	 *
	 * @param channel
	 * @exception
	 */
	private void sendUnLoginMessage(Channel channel) {
		// Message message = new Message();
		// message.setMsgType(NettyConstants.USER_UNLOGIN_MSG_TYPE);

		Message message = new Message();
		//
        // message.setErrorCode(NettyConstants.USER_UNLOGIN_MSG_TYPE);
        message.setErrorCode(ErrorCode.INVALID_SESSION);
		handlerDispatcher.sendMessage(channel, message);
	}

}
